#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <windows.h>
#include <event.h>
#include <database.h>

long getsp( void )
{
#if defined(_WINDOWS) && _MSC_VER==1600 && !defined(_WIN64)
    __asm mov eax, esp
    __asm add eax, 8
#else
#error unsupported architecture
#endif
}

event* event_create_raw( uint64 id, event *parent, long sp, ... )
{
    // max parameter size: 16MB
    static int p[1024*1024*16];
    int len = 0;
    event *e;
    e = (event *)malloc( sizeof(event) );
    e->id = id;
    e->parent = parent;
#if defined(_WINDOWS) && _MSC_VER==1600 && !defined(_WIN64)
    __asm
    {
        mov eax, 24
        lea ebx, dword ptr [p]
        add eax, ebp
        xor ecx, ecx
FINDSP:
        cmp eax, [ebp+20]
        je FOUND
        mov edx, [eax]
        add eax, 4
        mov [ecx+ebx], edx
        add ecx, 4
        jmp FINDSP
FOUND:
        mov [len], ecx
    }
#endif
    e->para_len = len;
    e->para = (char*)malloc(len);
    memcpy( e->para, p, len );
    return e;
}

void event_destroy( event *e )
{
    if( e != NULL )
    {
        if( e->para != NULL )
            free( e->para );
        free( e );
    }
}

void process( void *func, event *e )
{
#if defined( _WINDOWS ) && _MSC_VER==1600 && !defined(_WIN64)
    __asm
    {
        mov ebx, e
        mov ecx, [ebx+12]
        mov ebx, [ebx+8]
PUSH_PARA:
        test ecx, ecx
        je PUSH_DONE
        sub ecx, 4
        push dword ptr [ebx+ecx]
        jmp PUSH_PARA
PUSH_DONE:
        call dword ptr [func]
        mov ebx, e
        add esp, [ebx+12]
    }
#endif
}

event* current_event()
{
    event *evt = NULL;
    char key[128];
    DWORD id = GetCurrentThreadId();
    sprintf( key, "/frame/runtime/executing_event/%d", id );
    db_query( key, (void**)&evt );
    return evt;
}

void update_current_event( event *e )
{
    char key[128];
    DWORD id = GetCurrentThreadId();
    sprintf( key, "/frame/runtime/executing_event/%d", id );
    if( 0 != db_update( key, e ) )
        db_insert( key, e );
}
